/*
Copyright (C) 2009 Team16
This program is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. This program is distributed in the
hope that it will be useful, but WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License
for more details. You should have received a copy of the GNU General
Public License along with this program. If not, see <http://www.gnu.org/licens
*/
#include <QtGui>
#include "mainwindow.h"
#include <QtXml>
#include <QMessageBox>
#include <QTabBar>
#include <QtWebKit>
#include "previewform.h"
/*
Todo:
+0)Save
+1)Recent files
-2)Code\Recode\Show as ...
-5)Replace\find
-6)Regex replace\find
+7)Web Browser(Webkit based)
+4)Tabs
-10)QScript plugins
+11)Stats
+12)Projects\folder viewer
-13)Tart
-14)Masters
*/
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
	wnd=new QWidget(0,Qt::Window);
	//tabs
	{
		tabs=new QTabBar(wnd);
                tabs->addTab(tr("Code")); //0
                tabs->addTab(tr("Browser")); //1
                tabs->addTab(tr("Project")); //2
                tabs->addTab(tr("Help")); //3
                tabs->addTab(tr("Statistic")); //4
		tabs->show();
		connect (tabs,SIGNAL(currentChanged(int)),this,SLOT(tabchanged(int)));
	}
	// init
	{
		setupFileMenu();
		setupHelpMenu();
		this->hide();
		wnd->showMaximized();
		findCodecs();
		previewForm = new PreviewForm(this);
		previewForm->setCodecList(codecs);
	}
	//editor settings
	{
		QFont font;
		font.setFamily("Courier");
		font.setFixedPitch(true);
		font.setPointSize(12);
		editor = new QTextEdit(wnd);
		editor->setFont(font);
	}
	// tab 1,Code
	{
		highlighter = new Highlighter(editor->document());
		editor->show();
		mainl=new QVBoxLayout(wnd);

		mainl->addWidget(tabs);
		mainl->addWidget(editor);
		mainl->setMenuBar(this->menuBar() );
		wnd->setLayout(mainl);
	}
	// tab 2, Browser
	{
		web=new QVBoxLayout();
		wview = new QWebView(wnd);
		QHBoxLayout *navbar=new QHBoxLayout();
		lineEdit = new QLineEdit(wnd);
		lineEdit->setObjectName(QString::fromUtf8("lineEdit"));
		pushButton = new QPushButton(wnd);
		pushButton->setObjectName(QString::fromUtf8("GO"));
		pushButton->setGeometry(QRect(250, 120, 100, 23));
		connect(pushButton,SIGNAL(clicked()),this,SLOT(gobutton()));
		navbar->addWidget(lineEdit);
		navbar->addWidget(pushButton);
		web->addLayout(navbar);
		web->addWidget(wview);
		wview->load(QUrl("http://localhost/"));
		lineEdit->setText("http://localhost/");
		wview->show();
		mainl->addLayout(web);
	}
	// tab 3, Project
	{
		projectt=new QVBoxLayout();
		tree=new QTreeView(wnd);

		projst=QDir::currentPath();
		tree->setModel(&model);
		tree->setRootIndex(model.index(QDir::currentPath()));
		projectt->addWidget(tree);
		mainl->addLayout(projectt);
		connect(tree,SIGNAL(clicked(QModelIndex)),this,SLOT(treeclick(QModelIndex)));
	}
	// tab 4, help
	{
		help=new QHBoxLayout(wnd);
		mainl->addLayout(help);
		helptree=new QTreeView(wnd);
		helpmodel.setFilter(QDir::AllEntries | QDir::AllDirs | QDir::NoDotAndDotDot);
		helpmodel.setSorting(QDir::DirsFirst);
		helpmodel.setNameFilters(QStringList("*.html") );
		helptree->setModel(&helpmodel);
		helptree->setRootIndex(helpmodel.index(qApp->applicationDirPath()+"\\help\\"));
		helptree->hideColumn(1);
		helptree->hideColumn(2);
		helptree->hideColumn(3);
		sleft=new QVBoxLayout(wnd);
		suleft=new QHBoxLayout(wnd);
		findedit=new QLineEdit(wnd);
		search=new QPushButton(wnd);
		hview=new QWebView(wnd);
		hview->load(QUrl(qApp->applicationDirPath()+"/help/index.html"));
		hview->settings()->setUserStyleSheetUrl(QUrl(qApp->applicationDirPath()+"/help/style.css"));
		hview->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
		help->addLayout(sleft);
		suleft->addWidget(findedit);
		suleft->addWidget(search);
		sleft->addLayout(suleft);
		sleft->addWidget(helptree);
		help->addWidget(hview);
		search->setText("find");
		search->setSizePolicy(QSizePolicy::Fixed ,QSizePolicy::Minimum);
		findedit->setSizePolicy(QSizePolicy::Preferred,QSizePolicy::Minimum);
		helptree->setSizePolicy(QSizePolicy::Minimum,QSizePolicy::Expanding);
		helptree->expandAll();
		connect(helptree,SIGNAL(clicked(QModelIndex)),this,SLOT(helpclick(QModelIndex)));
	}
	// tab 5, stats
	{
		QFont font;
		font.setFamily("Courier");
		font.setFixedPitch(true);
		font.setPointSize(12);
		stat=new QTextEdit(wnd);
		mainl->addWidget(stat);
		stat->setFont(font);
		stat->setText("STAT!");
	}
	// last init, reading arguments
	{
		connect (wnd,SIGNAL(destroyed()),qApp,SLOT(quit()));
		tabchanged(0);
		if (qApp->argc()>1){
			openFile(qApp->arguments().at(1));
		}else{
			Setcurrent("");
		}
	}
}
void MainWindow::findCodecs()
{
	QMap<QString, QTextCodec *> codecMap;
	QRegExp iso8859RegExp("ISO[- ]8859-([0-9]+).*");
	foreach (int mib, QTextCodec::availableMibs()) {
		QTextCodec *codec = QTextCodec::codecForMib(mib);
		QString sortKey = codec->name().toUpper();
		int rank;
		if (sortKey.startsWith("UTF-8")) {
			rank = 1;
		} else if (sortKey.startsWith("UTF-16")) {
			rank = 2;
		} else if (iso8859RegExp.exactMatch(sortKey)) {
			if (iso8859RegExp.cap(1).size() == 1)
			rank = 3;
			else
			rank = 4;
		} else {
			rank = 5;
		}
		sortKey.prepend(QChar('0' + rank));
		codecMap.insert(sortKey, codec);
	}
	codecs = codecMap.values();
}
void MainWindow::treeclick(QModelIndex sd){
	QString txt;
	QModelIndex t;
	txt=sd.model()->data(sd.parent().child(sd.row(),0),0).toString();
	for (t=sd.parent();t.parent().isValid()==true;t=t.parent()){
		txt=t.data(0).toString()+"/"+txt ;
	}
	txt=t.data(0).toString()+"/"+txt ;
	QFileInfo fi(txt);
	if (fi.exists()==true && fi.isFile()){
		QMessageBox::StandardButton reply;
                reply = QMessageBox::question(wnd, tr("Close without saving?"),
                tr("Do you wish to open new file,without saving prevous one?")+"<br>"+fi.absoluteFilePath(),
		QMessageBox::Yes | QMessageBox::No);
		if (reply == QMessageBox::Yes)
		{
			openFile(fi.absoluteFilePath());
		}
		else
		{
			// no action
		}
	}
}
void MainWindow::helpclick(QModelIndex sd){
	QString txt;
	QModelIndex t;
	txt=sd.model()->data(sd.parent().child(sd.row(),0),0).toString();
	for (t=sd.parent();t.parent().isValid()==true;t=t.parent()){
		txt=t.data(0).toString()+"/"+txt ;
	}
	txt=t.data(0).toString()+"/"+txt ;
	QFileInfo fi(txt);
	if (fi.exists()==true && fi.isFile()){
		hview->load(QUrl(fi.absoluteFilePath()));
	}
}
void MainWindow::gobutton(){
	wview->load(QUrl(lineEdit->text()));
}
void MainWindow::tabchanged(int tab){
	editor->hide();
	wview->hide();
	lineEdit->hide();
	pushButton->hide();
	tree->hide();
	stat->hide();
	//
	findedit->hide();
	search->hide();
	helptree->hide();
	hview->hide();
	//
	switch(tab){
	case 0:
		editor->show();
		break;
	case 1:
		wview->show();
		lineEdit->show();
		pushButton->show();
		break;
	case 2:
		QFileInfo *po=new QFileInfo(curFile);
		tree->setRootIndex(model.index(po->dir().absolutePath()));
		tree->show();
		break;
	case 3:
		findedit->show();
		search->show();
		helptree->show();
		hview->show();
		break;
	case 4:
		QString txt=editor->document()->toPlainText();
		const QList<QTextCodec *> &list=codecs;
		QString codecsstring;
		foreach (QTextCodec *codec, list){
			codecsstring+=", "+codec->name();
		}
		QString st;
                st=QString(tr("Characters")+" : %1<br />"+
                tr("Lines")+" : %2<br />"+
                tr("Semicolon count")+" : %3<br />"+
                tr("Double spaces")+" : <b><font color=\"red\">%4</font></b><br />"+
                tr("Empty lines")+" : <b><font color=\"red\">%5</font></b><br />"+
                tr("Classes")+" : <u>%6</u><br />"+
                tr("Functions")+" : <u>%7</u><br />"+
                "<br /><hr /><br />"+
                tr("Language")+" : "+lang+"<br />"+
                tr("File")+" :"+curFile+"<br />"+
                "<br /><hr /><br />"+
                tr("Tide version")+" : <i>3.0</i> <br />"+
                tr("Build version")+" : <i>47</i> <br />"+
                tr("Maintainer")+" : <b>Bonapart</b>"\
                "<br /><hr /><br />"+
                tr("Instaled modules : <i>Code, Browser, Project explorer, Statistic</i><br />")+
                tr("Instaled code features : <i>QRegExp import, Encoding select with preview, <u>U</u>\\<i>I</i>\\<b>B</b> Formating</i><br />")+
                "<div align=\"right\">"+tr("Text encodings supported")+" : <i>"+codecsstring +"</i></div><br />"+
                tr("Instaled browser features")+" : <i>"+QDir(qApp->applicationDirPath()+"/imageformats").entryList(QString("*.dll").split(" "),QDir::Files,QDir::Name ).join(", ")+"</i><br />"+
                "<div align=\"right\">"+tr("Instaled code highlights")+" : <i>"+QDir(qApp->applicationDirPath()+"/data").entryList(QString("*.h").split(" "),QDir::Files,QDir::Name ).join(", ")+"</i></div>")
		.arg(txt.length(), 0, 10)
		.arg(txt.count("\n"),0,10)
		.arg(txt.count(";"),0,10)
		.arg(txt.count("  "),0,10)
		.arg(txt.count("\n\n"),0,10)
		.arg(txt.count("class"),0,10)
		.arg(txt.count("function"),0,10);
		// .arg( ,0,10);
		stat->setHtml(st);
		stat->show();
		break;
	}
}
void MainWindow::about()
{
	QMessageBox::about(wnd, tr("About TIDE.QT"),
	tr("<p> <b>Tide.QT</b> - is free Code editor for <br />" \
	"<br />" \
	"HTML ,"\
	"CSS ,"\
	"C++ ,"\
	"JavaScript ,"\
	"PHP"\
	"<br />" \
	"And it may edit other's with highlight plugin system<br />"\
	"Developer: <b>Bonapart</b>,contact by icq:175256"\
	"</p>"));
}
void MainWindow::newFile()
{
	editor->clear();
	Setcurrent("");
}
void MainWindow::openFile(const QString &path)
{
	QString fileName = path;
	if (fileName.isNull())
	fileName = QFileDialog::getOpenFileName(wnd,
	tr("Open File"), "", "C++ Files (*.cpp *.h);;PHP files (*.php *.pthml);;All files (*.*)");
	if (!fileName.isEmpty()) {
		QFile file(fileName);
		QString pf;
		QString ff;
		Setcurrent(fileName);
		if (file.open(QFile::ReadOnly | QFile::Text)){
			QByteArray data = file.readAll();
			previewForm->setEncodedData(data);
			if (previewForm->exec())
			editor->setPlainText(previewForm->decodedString());
		}
	}
}
void MainWindow::updateRecentFileActions()
{
	QSettings settings("Team16", "T16IDE");
	QString last=settings.value("last0").toString();
	QString last1=settings.value("last1").toString();
	QString last2=settings.value("last2").toString();
	QString last3=settings.value("last3").toString();
	QString last4=settings.value("last4").toString();
	recents[0]->setText(last);
	recents[0]->data()=last;
	recents[1]->setText(last1);
	recents[1]->data()=last1;
	recents[2]->setText(last2);
	recents[2]->data()=last2;
	recents[3]->setText(last3);
	recents[3]->data()=last3;
	recents[4]->setText(last4);
	recents[4]->data()=last4;
	for (int i=0;i<5;i++){
		recents[i]->setVisible(recents[i]->text()!="");
	}
	int numRecentFiles=( (last!="")+(last1!="")+(last2!="")+(last3!="")+(last4!="") );
	separatorAct->setVisible(numRecentFiles > 0);
}
void MainWindow::Setcurrent(const QString &fileName){
	curFile = fileName;
	if (curFile.isEmpty()){
		wnd->setWindowTitle("T16IDE");
		highlighter->init("def");
		lang="def";
	}
	else{
                wnd->setWindowTitle(tr("%2 - %1","translate not needed").arg(curFile)
		.arg(tr("T16IDE")));
		QFileInfo fi(curFile);
		highlighter->init(fi.completeSuffix().trimmed() );
		lang=fi.completeSuffix().trimmed();
		QSettings settings("Team16", "T16IDE");
		settings.setValue("last4", settings.value("last3").toString());
		settings.setValue("last3", settings.value("last2").toString());
		settings.setValue("last2", settings.value("last1").toString());
		settings.setValue("last1", settings.value("last0").toString());
		settings.setValue("last0", curFile);
	}
	updateRecentFileActions();
}
void MainWindow::openRec()
{
	QString fileName;
	QAction *action = qobject_cast<QAction *>(sender());
	if (action)
	fileName =action->text();
	if (!fileName.isEmpty()) {
		openFile(fileName);
	}
}
void MainWindow::saveFile(const QString &path)
{
	QString fileName = path;
	if (fileName.isNull())
	fileName = QFileDialog::getSaveFileName(wnd,
        tr("Save File"), "", "C++ Files (*.cpp *.h);;PHP files (*.php *.pthml)");
	if (!fileName.isEmpty()) {
		QFile file(fileName);
		QString pf;
		pf=editor->toPlainText();
		if (!file.open(QFile::WriteOnly | QFile::Text)) {
			QMessageBox::warning(wnd, tr("Application"),
			tr("Cannot write file %1:\n%2.")
			.arg(fileName)
			.arg(file.errorString()));
		}
		QTextStream out(&file);
		QApplication::setOverrideCursor(Qt::WaitCursor);
		out << pf;
		QApplication::restoreOverrideCursor();
	}
}
void MainWindow::setupEditor()
{
}
void MainWindow::setupFileMenu()
{
	QMenu *fileMenu = new QMenu(tr("&File"), this);
	this->menuBar()->addMenu(fileMenu);
	fileMenu->addAction(tr("&New"), this, SLOT(newFile()),
	QKeySequence(tr("Ctrl+N",
	"File|New")));
	fileMenu->addAction(tr("&Open..."), this, SLOT(openFile()),
	QKeySequence(tr("Ctrl+O",
	"File|Open")));
	fileMenu->addAction(tr("&Save..."), this, SLOT(saveFile()),
	QKeySequence(tr("Ctrl+S",
	"File|Save")));
	separatorAct = fileMenu->addSeparator();
	int MaxRecentFiles=5;
	for (int i = 0; i < MaxRecentFiles; ++i){
		recents[i]=fileMenu->addAction("", this, SLOT(openRec()));
		recents[i]->setVisible(false);
	}
	fileMenu->addSeparator();
	updateRecentFileActions();
	menuBar()->addSeparator();
	fileMenu->addAction(tr("E&xit"), qApp, SLOT(quit()),
	QKeySequence(tr("Ctrl+Q",
	"File|Exit")));
}
void MainWindow::setupHelpMenu()
{
	QMenu *helpMenu = new QMenu(tr("&Help"), this);
	menuBar()->addMenu(helpMenu);
	helpMenu->addAction(tr("&About"), this, SLOT(about()));
	helpMenu->addAction(tr("About &Qt"), qApp, SLOT(aboutQt()));
}
